
#include <stdlib.h>     // Header file for malloc/free.
#include <stdio.h>      // Header file for standard file i/o.
#include <GL/glut.h>    // Header File For The GLUT Library 
#include <iostream>
#include <math.h>

#include "Timer.h"
#include "MathMisc.h"
#include "GlobalSettings.h"
#include "UtilFunctions.h"

#include "MegaMan.h"

int window;

Timer fps;

float mX = 0, mY = 40, mZ = 0;
float cR = 320, cY = 80, cA = 270, cF = -10;

MegaMan Mega(0, 40, 0);

using namespace std;

bool InitGL (int Width, int Height )
{
	if ( SDL_Init(SDL_INIT_TIMER) )
		return false;

	memset( KeyDown, false, sizeof( KeyDown ) );
	memset( KeyDownSpecial, false, sizeof( KeyDownSpecial ) );

	// Setup Perspective
	glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,16000.0f);	// Calculate The Aspect Ratio Of The Window
    glMatrixMode(GL_MODELVIEW);

	return true;
}

void GLDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor( 1.0, 1.0, 1.0, 0.0 );	//get white background color
//	if (!fps.is_started())
//		fps.start();

	// Begin the View
	glLoadIdentity();

	// Camera - Working on a boom. Always follows MegaMan!
	// Must be done FIRST. Edits ModelView Matrix.
	gluLookAt(mX+cR*sin(toRadian(cA)), cY+mY, mZ+cR*cos(toRadian(cA)), mX, cF, mZ, 0, 1, 0);

	glPushMatrix();

	// Draw ground
	glColor3f(0.0f, 1.0f, 0.0);
	glBegin(GL_QUADS);
		for (int x = 0; x < 20; x++)
		{
			for (int y = 0; y < 20; y++)
			{	
				float height = 0;
				if (x == y && x%5 == 0)
					height = 32;
				glVertex3f(x*80, height, -y*80); 
				glVertex3f(x*80, height, -(y+1)*80);
				glVertex3f((x+1)*80, height, -(y+1)*80);
				glVertex3f((x+1)*80, height, -y*80);
			}
		}
	glEnd();
	glPopMatrix();

	//// Lets draw MegaManCube
	Mega.Update();
	//glPushMatrix();

	//glTranslatef(mX, mY, mZ);
	//glScalef(1, 2.5f, 1);
	//glColor3f(0.0f, 0.0f, 1.0f);
	//glutSolidCube(32.0f);

	//glPopMatrix();

	glutSwapBuffers();

	// If we want to cap the frame rate
/*	if (fps.get_ticks() < 1000 / 60) 
	{
		// Sleep the remaining frame time
		SDL_Delay( (1000/60) - fps.get_ticks() );
		fps.stop();
	}
*/
}

void GLIdle(void)
{
	glutPostRedisplay();
}

void GLResize(int Width, int Height)
{
    if (Height==0)				// Prevent A Divide By Zero If The Window Is Too Small
	Height=1;

    glViewport(0, 0, Width, Height);		// Reset The Current Viewport And Perspective Transformation

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,16000.0f);
    glMatrixMode(GL_MODELVIEW);
}

/* The function called whenever a key is pressed. */
void HandleInputDown(unsigned char key, int x, int y) 
{
    /* If escape is pressed, kill everything. */
    switch(key)
    { 
		// Close Program
		case 27: // Escape
			glutDestroyWindow(window); 
			exit(0);
			break;

		case 'a':
			cA -= 2.0f;
			break;
		case 'd':
			cA += 2.0f;
			break;
		case 'w':
			cY += 2.0f;
			break;
		case 's':
			cY -= 2.0f;
			break;
		case 'q':
			cF -= 2.0f;
			break;
		case 'e':
			cF += 2.0f;
			break;
    }
	Mega.HandleInput();
	glutPostRedisplay();
}

void HandleInputUp(unsigned char key, int x, int y) 
{
    /* If escape is pressed, kill everything. */
    switch(key)
    { 
		// Close Program
		case 27: // Escape
			glutDestroyWindow(window); 
			exit(0);
			break;

		case 'a':
			cA -= 2.0f;
			break;
		case 'd':
			cA += 2.0f;
			break;
		case 'w':
			cY += 2.0f;
			break;
		case 's':
			cY -= 2.0f;
			break;
		case 'q':
			cF -= 2.0f;
			break;
		case 'e':
			cF += 2.0f;
			break;
    }

	Mega.HandleInput();
	glutPostRedisplay();
}

// Special key function.
void SpecialInput(int key, int x, int y)
{
	switch (key)
	{
		case GLUT_KEY_UP:
			KeyDownSpecial[0] = true;
			break;
		case GLUT_KEY_DOWN:
			KeyDownSpecial[1] = true;
			break;
		case GLUT_KEY_LEFT:
			KeyDownSpecial[2] = true;
			break;
		case GLUT_KEY_RIGHT:
			KeyDownSpecial[3] = true;
			break;
		case GLUT_KEY_F1:
			glutFullScreen();
			break;
		case GLUT_KEY_F2:
			glutReshapeWindow (1024, 768);
			break;
	}
	Mega.HandleInput();
	glutPostRedisplay();
}

void SpecialInputUp(int key, int x, int y)
{
	switch (key)
	{
		case GLUT_KEY_UP:
			KeyDownSpecial[0] = false;
			break;
		case GLUT_KEY_DOWN:
			KeyDownSpecial[1] = false;
			break;
		case GLUT_KEY_LEFT:
			KeyDownSpecial[2] = false;
			break;
		case GLUT_KEY_RIGHT:
			KeyDownSpecial[3] = false;
		case GLUT_KEY_F1:
			glutFullScreen();
			break;
		case GLUT_KEY_F2:
			glutReshapeWindow (1024, 768);
			break;
	}
	Mega.HandleInput();
	glutPostRedisplay();
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);

	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(0,0);

	window = glutCreateWindow("MegaManGL - Land Demo");
	
	glutDisplayFunc(&GLDisplay);
	glutIdleFunc(&GLIdle);
	glutReshapeFunc(&GLResize);
	glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);
	glutKeyboardFunc(&HandleInputDown);
	glutKeyboardUpFunc(&HandleInputUp);
	glutSpecialFunc(&SpecialInput);
	glutSpecialUpFunc(&SpecialInputUp);


	if( InitGL(1024, 768) )
		glutMainLoop();

	return 1;
}